package com.evil.common.oss.service;

import cn.hutool.core.date.DateUtil;
import com.evil.common.core.enums.RCodeEnum;
import com.evil.common.core.exception.BusinessException;
import com.evil.common.file.enums.FileServiceProviderEnum;
import com.evil.common.oss.props.LocalOssProperty;
import com.evil.common.oss.util.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.Date;

/**
 * 本地文件OSS
 */
@Slf4j
public class LocalOssFileStorageService extends FileStorageService {

    private final LocalOssProperty property;

    public LocalOssFileStorageService(LocalOssProperty property) {
        this.property = property;
    }

    /**
     * 获取访问域名
     *
     * @return String
     */
    @Override
    public String getHost() {
        return property.getHost();
    }

    /**
     * 获取预览域名
     *
     * @return String
     */
    @Override
    public String getPreview() {
        return property.getPreview();
    }

    /**
     * 获取访问文件路径
     *
     * @return String
     */
    @Override
    public String getVisitPath() {
        return property.getVisitPath();
    }

    /**
     * 获取OSS类型
     *
     * @return int
     */
    @Override
    public int getServiceProvider() {
        return FileServiceProviderEnum.LOCAL.getId();
    }

    /**
     * 获取文件URL参数
     *
     * @param path     path
     * @return String fileName=FILE
     */
    @Override
    public String getFileUrl(String path) {
        return this.getPreview() + path;
    }

    /**
     * 获取文件URL
     *
     * @param path path
     * @param fileName fileName
     */
    @Override
    public String getDownloadUrl(String path, String fileName) {
        // 本地环境需要凭借文件名参数
        return this.getPreview() + path + "?fileName=" + fileName;
    }

    /**
     * 文件上传
     *
     * @param data           data
     * @param path           path
     * @param sourceFileName sourceFileName
     * @return String
     */
    @Override
    public String upload(byte[] data, String path, String sourceFileName, String contentType, boolean isPreview) {
        return upload(new ByteArrayInputStream(data), path, sourceFileName, contentType, isPreview);
    }

    /**
     * 文件上传
     *
     * @param inputStream    inputStream
     * @param path           path
     * @param sourceFileName sourceFileName
     * @return String
     */
    @Override
    public String upload(InputStream inputStream, String path, String sourceFileName, String contentType, boolean isPreview) {
        if (inputStream == null) {
            return null;
        }
        // 获取文件名
        String[] paths = path.split("/");
        if (!paths[paths.length - 1].contains(".")) {
            throw new BusinessException(RCodeEnum.ERROR_FILE_NOT_FOUND);
        }
        String fileName = paths[paths.length - 1];
        path = StringUtils.join(Arrays.copyOf(paths, paths.length - 1), "/");
        String filePath = property.getSavePath() + "/" + path;
        try {
            FileUtil.writeFile(filePath, fileName, inputStream);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BusinessException(RCodeEnum.ERROR_FILE, "文件上传失败，异常：" + e.getMessage());
        }
        return property.getVisitPath() + "/" + path + "/" + fileName;
    }

    /**
     * 获取文件
     *
     * @param filePath filePath
     * @param file     输出的文件
     * @return File
     */
    @Override
    public File getFileByFilePath(String filePath, File file) {
        if (StringUtils.isBlank(filePath)) {
            return null;
        }
        filePath = property.getSavePath() + "/" + filePath;
        try {
            return new File(filePath);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BusinessException(RCodeEnum.ERROR_FILE, "文件获取失败，异常：" + e.getMessage());
        }
    }

    /**
     * 获取下载URL
     *
     * @param filePath       文件path
     * @param fileName       文件名称
     * @param expirationTime 过期时间
     * @return URL
     */
    @Override
    public URL getDownloadUrl(String filePath, String fileName, Date expirationTime) {
        if (DateUtil.compare(new Date(), expirationTime) > 0) {
            throw new BusinessException(RCodeEnum.FILE_OVERDUE);
        }
        try {
            return new URL(this.getDownloadUrl(filePath, fileName));
        } catch (MalformedURLException e) {
            log.error(e.getMessage(), e);
            throw new BusinessException(RCodeEnum.ERROR_FILE, "获取文件失败，异常：" + e.getMessage());
        }
    }
}
